<template>
  <div class="webgl-windmill">
    <h1>WEBGL风车效果</h1>
    <p>使用WebGL实现风车效果，展示如何使用片元着色器创建旋转的风车图案。</p>

    <el-card class="demo-section">
      <template #header>
        <div class="card-header">
          <h3>风车效果展示</h3>
        </div>
      </template>
      <div class="demo-content">
        <canvas ref="demoCanvas" width="600" height="400"></canvas>
        <div class="control-panel">
          <el-form :model="windmillForm" label-width="100px">
            <el-form-item label="旋转速度">
              <el-slider
                v-model="windmillForm.speed"
                :min="0.1"
                :max="2.0"
                :step="0.1"
                @change="updateWindmill"
              />
            </el-form-item>
          </el-form>
        </div>
      </div>
    </el-card>

    <el-card class="code-section">
      <template #header>
        <div class="card-header">
          <h3>着色器代码</h3>
        </div>
      </template>
      <div class="code-content">
        <pre><code class="glsl">
  // 顶点着色器
  attribute vec4 a_Position;
  void main() {
    gl_Position = a_Position;
  }
        </code></pre>
        <pre><code class="glsl">
  // 片元着色器
  precision mediump float;
  uniform float u_Time;
  uniform vec2 u_Resolution;
  uniform float u_Speed;

  void main() {
    vec2 p = (gl_FragCoord.xy - 0.5 * u_Resolution) / min(u_Resolution.x, u_Resolution.y);
    float t = atan(p.y, p.x) + u_Time * u_Speed;
    t = sin(t * 10.0);
    float d = smoothstep(0.41, 0.4, length(p));
    gl_FragColor = vec4(vec3(0.1/t*d), 1.0);
  }
        </code></pre>
      </div>
    </el-card>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, reactive } from 'vue'
import { WebGLUtils } from '@/utils/webgl'

const demoCanvas = ref<HTMLCanvasElement | null>(null)
let gl: WebGLRenderingContext | null = null
let program: WebGLProgram | null = null
// 创建WebGL工具实例
const webglUtils = ref<WebGLUtils | null>(null)
// 表单数据
const windmillForm = reactive({
  speed: 0.5
})

// 初始化顶点缓冲区
function initVertexBuffers(gl: WebGLRenderingContext, program: WebGLProgram) {
  // 创建覆盖整个canvas的矩形
  const vertices = new Float32Array([
    -1.0, 1.0,
    -1.0, -1.0,
    1.0, 1.0,
    1.0, -1.0
  ])

  // 创建缓冲区
  const vertexBuffer = gl.createBuffer()
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)
  gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)

  // 获取attribute变量的位置
  const a_Position = gl.getAttribLocation(program, 'a_Position')

  // 将缓冲区分配给a_Position变量
  gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0)
  gl.enableVertexAttribArray(a_Position)
}

// 渲染场景
function render() {
  if (!gl || !program || !demoCanvas.value) return

  // 设置视口和清除颜色
  gl.viewport(0, 0, demoCanvas.value.width, demoCanvas.value.height)
  gl.clearColor(0.0, 0.0, 0.0, 1.0)
  gl.clear(gl.COLOR_BUFFER_BIT)

  // 获取uniform变量位置
  const u_Resolution = gl.getUniformLocation(program, 'u_Resolution')
  const u_Time = gl.getUniformLocation(program, 'u_Time')
  const u_Speed = gl.getUniformLocation(program, 'u_Speed')

  // 设置uniform变量值
  gl.uniform2f(u_Resolution, demoCanvas.value.width, demoCanvas.value.height)
  gl.uniform1f(u_Time, performance.now() / 1000.0)
  gl.uniform1f(u_Speed, windmillForm.speed)

  // 绘制矩形
  gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)

  // 请求下一帧
  requestAnimationFrame(render)
}

// 更新风车效果
function updateWindmill() {
  render()
}

// 初始化WebGL
const initWebGL = () => {
  if (!demoCanvas.value) return

  // 获取WebGL上下文
  gl = demoCanvas.value.getContext('webgl')
  if (!gl) {
    console.error('Failed to get WebGL context')
    return
  }

  // 创建WebGL工具实例
  webglUtils.value = new WebGLUtils(gl)

  // 顶点着色器源码
  const vertexShaderSource = `
    attribute vec4 a_Position;
    void main() {
      gl_Position = a_Position;
    }
  `

  // 片元着色器源码
  const fragmentShaderSource = `
    precision mediump float;
    uniform float u_Time;
    uniform vec2 u_Resolution;
    uniform float u_Speed;

    void main() {
      vec2 p = (gl_FragCoord.xy - 0.5 * u_Resolution) / min(u_Resolution.x, u_Resolution.y);
      float t = atan(p.y, p.x) + u_Time * u_Speed;
      t = sin(t * 10.0);
      float d = smoothstep(0.41, 0.4, length(p));
      gl_FragColor = vec4(vec3(0.2/t*d), 1.0);
    }
  `

  const vertexShader = webglUtils.value.createShader(gl.VERTEX_SHADER, vertexShaderSource)
  const fragmentShader = webglUtils.value.createShader(gl.FRAGMENT_SHADER, fragmentShaderSource)
  if (!vertexShader || !fragmentShader) return

  // 创建着色器程序
  program = webglUtils.value.createProgram(vertexShader, fragmentShader)
  if (!program) {
    console.error('Failed to create program')
    return
  }

  // 使用程序对象
  gl.useProgram(program)

  // 初始化顶点缓冲区
  initVertexBuffers(gl, program)

  // 开始渲染
  render()
}

// 组件挂载时初始化WebGL
onMounted(() => {
  initWebGL()
})
</script>

<style lang="scss" scoped>
.webgl-windmill {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;

  h1 {
    color: #303133;
    margin-bottom: 20px;
  }

  p {
    margin-bottom: 30px;
  }

  .demo-section,
  .code-section {
    margin: 30px 0;

    .card-header {
      display: flex;
      align-items: center;

      h3 {
        margin: 0;
        color: #409EFF;
      }
    }
  }

  .demo-section {
    .demo-content {
      display: flex;
      gap: 20px;
      justify-content: center;

      canvas {
        border: 1px solid #dcdfe6;
        background-color: #000;
      }

      .control-panel {
        flex: 1;
        padding: 20px;
      }
    }
  }

  .code-section {
    .code-content {
      background-color: #f8f9fa;
      padding: 15px;
      border-radius: 4px;
      max-height: 500px;
      overflow-y: auto;

      code {
        font-family: monospace;
        color: #409EFF;
      }

      pre {
        margin: 0;
        white-space: pre-wrap;
      }
    }
  }
}
</style>
